package com.io.utils.shiro;

import com.google.common.base.Strings;
import com.io.constant.Constant;
import com.io.dao.SysMenuDao;
import com.io.dao.SysRoleDao;
import com.io.dao.SysUserDao;
import com.io.entity.SysMenuEntity;
import com.io.entity.SysUserEntity;
import com.io.exception.SelfException;
import com.io.service.SysUserService;
import com.io.utils.RedisUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.util.*;

/**
 * The class/interface 认证
 *
 * @author guod
 * @version 1.0 use jdk 1.8
 */
@Slf4j
@Component
public class UserRealm extends AuthorizingRealm {
    @Autowired
    private RedisUtils redisUtils;

    @Autowired
    private SysUserService userService;

    @Autowired
    private SysRoleDao sysRoleDao;

    @Autowired
    private SysUserDao sysUserDao;

    @Autowired
    private SysMenuDao sysMenuDao;

    /**
     * 必须重写此方法，不然Shiro会报错
     */
    @Override
    public boolean supports(AuthenticationToken token) {
        return token instanceof JwtToken;
    }

    /**
     * 用户身份识别(登录")
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) {
        String token = (String) authenticationToken.getCredentials();
        // 解密获得username，用于和数据库进行对比
        String username = JwtUtil.getUsername(token);
        if (Strings.isNullOrEmpty(username)) {
            throw new AuthenticationException("token非法无效!");
        }
        // 查询用户信息
        SysUserEntity sysUser = userService.selectByUsername(username);
        if (StringUtils.isEmpty(sysUser)) {
            throw new SelfException("用户不存在!");
        }
        // 校验token有效性
        if (!JwtUtil.verify(token, username, sysUser.getPassword())) {
            throw new AuthenticationException("Username or password error");
        }
        // 判断用户状态
        return new SimpleAuthenticationInfo(sysUser, token, ByteSource.Util.bytes(sysUser.getSalt()), getName());
    }

    /**
     * 访问控制。比如某个用户是否具有某个操作的使用权限
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        SysUserEntity user = (SysUserEntity) principalCollection.getPrimaryPrincipal();
        Long userId = user.getUserId();

        List<String> permsList;

        // 系统管理员，拥有最高权限
        if (userId == Constant.SUPER_ADMIN) {
            List<SysMenuEntity> menuList = sysMenuDao.selectList(null);
            permsList = new ArrayList<>(menuList.size());
            for (SysMenuEntity menu : menuList) {
                permsList.add(menu.getPerms());
            }
        } else {
            permsList = sysUserDao.queryAllPerms(userId);
        }

        // 用户权限列表
        Set<String> permsSet = new HashSet<>();
        for (String perms : permsList) {
            if (org.apache.commons.lang.StringUtils.isBlank(perms)) {
                continue;
            }
            permsSet.addAll(Arrays.asList(perms.trim().split(",")));
        }

        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        info.setStringPermissions(permsSet);
        return info;
    }
}
